﻿using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using HandyControl.Controls;
using HardToolApp.Model;
using HardToolApp.Tool;
using HardToolApp.View;
using KeraLua;
using NLua;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HardToolApp.ViewModel
{
    [ViewModelHelper("SPI主机", typeof(SPIMasterPage), typeof(SPIMasterModel), Sort = 6)]
    internal class SPIMasterVM : CommVM
    {
        public RelayCommand writeReadCmd { get; set; }
        
        public SPIMasterVM() 
        {
            writeReadCmd = new RelayCommand(WriteReadData);

            ScriptVM.register("spi_master_set", "(数据长度,MSB,波特率,CPOL,CPHA)", "SPI_MASTER", this.GetType(), "设置spi主机参数，数据长度0:8,1:16;MSB 0:高位在前,1低位在前;波特率 0:18M,1:9M,2:4.5M,3:2.25M,4:1125K,5:562.5K,5:281.25K;CPOL:0:CLK空闲时低电平,1:高电平;CPHA 0:第一个边沿采样,1:第二个边沿", "0:操作成功,1:操作失败");
            ScriptVM.register("spi_master_send", "(发送数据,dc电平)", "SPI_MASTER", this.GetType(), "spi主机发送数据", "0:操作成功,1:操作失败");
            ScriptVM.register("spi_master_send_byte", "(发送数据:byte数组,dc电平)", "SPI_MASTER", this.GetType(), "spi主机发送数据", "0:操作成功,1:操作失败");
            ScriptVM.register("spi_master_read", "(读取长度,dc电平)", "SPI_MASTER", this.GetType(), "spi主机读取数据", "0:操作成功,1:操作失败");
            ScriptVM.register("spi_master_read_send", "(发送数据,读取长度,dc电平)", "SPI_MASTER", this.GetType(), "spi主机发送并读取数据", "0:操作成功,1:操作失败");

        }

        private void WriteReadData()
        {
            if(string.IsNullOrEmpty(((SPIMasterModel)Model).sendBytes))
            {
                Growl.Warning("发送区为空！");
                return;
            }
            ((SPIMasterModel)Model).subCmd = (byte)Communicate.SubCmd.SendReadData;
            Send((SPIMasterModel)Model);
        }

        // 接收
        public override void RecOkData(byte[] b)
        {
            switch (b[4])
            {
                case (byte)CommSubCmdSPIMaster.COMM_SUB_SPI_MASTER_READ://数据接收
                    ((SPIMasterModel)Model).receiveBytes = Common.Byte2String(b.Skip(6).ToArray(), len: b[2] - 7);
                    USBInfoVM.USBVm.AddMap((b[3] << 8) + b[4], Common.String2Byte(((SPIMasterModel)Model).receiveBytes));
                    break;
                case (byte)CommSubCmdSPIMaster.COMM_SUB_SPI_MASTER_WRITE_READ://数据接收
                    ((SPIMasterModel)Model).receiveBytes = Common.Byte2String(b.Skip(6).ToArray(), len: b[2] - 7);
                    USBInfoVM.USBVm.AddMap((b[3] << 8) + b[4], Common.String2Byte(((SPIMasterModel)Model).receiveBytes));
                    break;
                default:
                    USBInfoVM.USBVm.AddMap((b[3] << 8) + b[4], 0);
                    break;
            }
        }
        #region SPIMaster
        public static object spi_master_set(byte dataSize,byte firstBit,byte baud,byte CPOL, byte CPHA)
        {
            byte[] bytes = new byte[11];
            bytes[0] = 0x55;
            bytes[1] = 0xaa;
            bytes[2] = 11;
            bytes[3] = (byte)CommCmd.COMM_SPI_MASTER;
            bytes[4] = (byte)CommSubCmdSPIMaster.COMM_SUB_SPI_MASTER_SET_PARAM;
            bytes[5] = dataSize;
            bytes[6] = (byte)firstBit;
            bytes[7] = (byte)baud;
            bytes[8] = (byte)CPOL;
            bytes[9] = (byte)CPHA;
            bytes[10] = Common.chksum(bytes);
            return USBInfoVM.USBVm.send(bytes);
        }
        public static object spi_master_send(string sendBytes,byte dcLevel)
        {
            byte[] data = Common.String2Byte(sendBytes);
            byte[] bytes = new byte[data.Count() + 7];
            bytes[0] = 0x55;
            bytes[1] = 0xaa;
            bytes[2] = (byte)(data.Count() + 7);
            bytes[3] = (byte)CommCmd.COMM_SPI_MASTER;
            bytes[4] = (byte)CommSubCmdSPIMaster.COMM_SUB_SPI_MASTER_WRITE;
            bytes[5] = (byte)(dcLevel);
            data.CopyTo(bytes, 6);
            bytes[data.Count() + 6] = Common.chksum(bytes);
            return USBInfoVM.USBVm.send(bytes);
        }
        public static object spi_master_send_byte(LuaTable sendBytes, byte dcLevel)
        {
            byte[] data = Common.Lua2Byte(sendBytes);
            byte[] bytes = new byte[data.Count() + 7];
            bytes[0] = 0x55;
            bytes[1] = 0xaa;
            bytes[2] = (byte)(data.Count() + 7);
            bytes[3] = (byte)CommCmd.COMM_SPI_MASTER;
            bytes[4] = (byte)CommSubCmdSPIMaster.COMM_SUB_SPI_MASTER_WRITE;
            bytes[5] = (byte)(dcLevel);
            data.CopyTo(bytes, 6);
            bytes[data.Count() + 6] = Common.chksum(bytes);
            return USBInfoVM.USBVm.send(bytes);
        }
        public static object spi_master_read(byte readLen,byte dcLevel)
        {
            byte[] bytes = new byte[8];
            bytes[0] = 0x55;
            bytes[1] = 0xaa;
            bytes[2] = 8;
            bytes[3] = (byte)CommCmd.COMM_SPI_MASTER;
            bytes[4] = (byte)CommSubCmdSPIMaster.COMM_SUB_SPI_MASTER_READ;
            bytes[5] = readLen;
            bytes[6] = dcLevel;
            bytes[7] = Common.chksum(bytes);
            return USBInfoVM.USBVm.send(bytes);
        }
        public static object spi_master_read_send(string sendBytes,byte readWriteLen, UInt32 writeDelay,byte dcLevel)
        {
            byte[] data = Common.String2Byte(sendBytes);
            byte[] bytes = new byte[data.Count() + 12];
            bytes[0] = 0x55;
            bytes[1] = 0xaa;
            bytes[2] = (byte)(data.Count() + 12);
            bytes[3] = (byte)CommCmd.COMM_SPI_MASTER;
            bytes[4] = (byte)CommSubCmdSPIMaster.COMM_SUB_SPI_MASTER_WRITE_READ;
            bytes[5] = readWriteLen;
            bytes[6] = (byte)(writeDelay >> 24);
            bytes[7] = (byte)(writeDelay >> 16);
            bytes[8] = (byte)(writeDelay >> 8);
            bytes[9] = (byte)(writeDelay & 0xff);
            bytes[10] = dcLevel;
            data.CopyTo(bytes, 11);
            bytes[data.Count() + 11] = Common.chksum(bytes);
            return USBInfoVM.USBVm.send(bytes);
        }
        /// <summary>
        /// 设置SPI参数
        /// </summary>
        /// <param name="m"></param>
        public override void Send(Peripheral peripheral)
        {
            SPIMasterModel m = (SPIMasterModel)peripheral;
            if (m.subCmd == (byte)Communicate.SubCmd.SetParam)
            {
                spi_master_set((byte)m.dataSize, (byte)m.firstBit, (byte)m.baud, (byte)m.CPOL, (byte)m.CPHA);
            }
            else if (m.subCmd == (byte)Communicate.SubCmd.SendData)
            {
                spi_master_send(m.sendBytes, (byte)(m.dcLevel == true ? 1 : 0));
            }
            else if (m.subCmd == (byte)Communicate.SubCmd.ReadData)
            {
                spi_master_read(m.readLen, (byte)(m.dcLevel == true ? 1 : 0));
            }
            else if (m.subCmd == (byte)Communicate.SubCmd.SendReadData)
            {
                spi_master_read_send(m.sendBytes,m.readWriteLen,m.writeDelay, (byte)(m.dcLevel == true ? 1 : 0));
            }
        }
        #endregion
    }
}
